from  flask_classy import FlaskView, route
from ..models.offer import Offer
from ..models.currency import Currency
from ..schema.param import pagination_param, new_offer_param
from ..schema.object import OfferFilterSchema, offer_price_state_schema, OfferSchema
from ..schema.error import NO_PARAM_ERROR, NEW_PARAM_ERROR, SERVER_ERROR
from ..schema.resp import ProductOfferResp
from flask import request, g, jsonify
from . import require_login
from ..models.product import Product
from ..models.currency import Currency
from  marshmallow import ValidationError
import datetime
from . import jsonify_with_error
from ..models.admin_user import AdminUser

def create_cdk_inventory(offer, inventory):
    from ..models.inventory import Ticket
    if inventory:
        cdks = inventory.get('cdks')
        if cdks:
            ticket_list = []
            now = datetime.datetime.now()
            count = 0
            for cdk in [x for x in cdks if len(x.strip()) > 0]:
                ticket_list.append(
                    {
                        'value': cdk,
                        'key': '',
                        'status': 'normal',
                        'offer': offer,
                        'updated_at': now
                    }
                )
                count += 1
            Ticket.insert_many(ticket_list).execute()
            offer.count = count
    if offer.is_dirty():
        offer.save()


def create_inventory(offer, inventory):
    if offer.slug == 'CD-KEY':
        create_cdk_inventory(offer, inventory)


class OffersView(FlaskView):
    @route("/", methods=['POST'])
    @require_login
    def new(self):
        if request.data:
            data, errors = new_offer_param.load(request.get_json())
            try:

                if errors: return NEW_PARAM_ERROR.jsonify(errors)
                product = data.get('product')
                currency = data.get('currency')
                price = data.get('price')
                type = data.get("type")
                member = g.member
                main_currency = Currency.get_main_currency()
                from decimal import Decimal
                price = Decimal.from_float(price)
                if not main_currency.id == currency.id:
                    price = round(price / currency.rate, 4)

                offer = Offer.create(
                    product=product,
                    price=price,
                    slug=type,
                    member=member
                )
                create_inventory(offer, data.get('inventory'))
                offer_schema = OfferSchema(many=False)
                offer_schema.context = {'currency': currency}

                return offer_schema.jsonify(offer)
                print(offer)
            except ValidationError as ve:
                print(ve)
            except Exception as e:
                print(e)
                return SERVER_ERROR.jsonify()
        else:
            return NO_PARAM_ERROR.jsonify()

    @route('/filter', methods=['POST'])
    @require_login
    def filter(self):
        data = request.get_json()
        page_size = 10
        current_page = 1
        if 'pagination' in data:
            pagination = data.pop('pagination')
            page_size = pagination.get('page_size', 10)
            current_page = pagination.get('current_page', 1)

        member = g.member

        currency = None
        if 'currency' in data:

            currency = Currency.get_or_none(Currency.id == data.pop('currency'))
        else:
            currency = Currency.get_main_currency()
        offer_list = Offer.select().where(Offer.member == member).order_by(Offer.updated_at.desc(), False)

        offer_filter_schema = OfferFilterSchema()

        offer_filter_schema.context['currency'] = currency
        return offer_filter_schema.jsonify({
            'pagination': {
                'total': offer_list.count(),
                'current_page': current_page,
                'page_size': page_size
            },
            'currency': currency,
            'items': list(offer_list.paginate(int(current_page), int(page_size)))
        })

    @route('/price_stats', methods=['POST'])
    @require_login
    def price_stat(self):
        data = request.get_json()
        if data and 'product_id' in data:

            currency_id = data.get('currency', None)
            if 'currency' in data:
                currency = Currency.first(Currency.id == currency_id)
            else:
                currency = Currency.get_main_currency()

            product_id = data['product_id']
            if not isinstance(product_id, (list, tuple)):
                product_id = [product_id]
            rv = {}
            for pid in product_id:
                product = Product.first(Product.id == pid)
                offer = Offer.stat_price(product)
                rv[pid] = {
                    'minimum': Offer.convert_currency(offer.minimum, currency),
                    'average': Offer.convert_currency(offer.average, currency),
                    'maximum': Offer.convert_currency(offer.maximum, currency)
                }
            print(rv)
            return offer_price_state_schema.jsonify({
                'currency': currency,
                'data': rv
            })

    @route('/product/<product_id>')
    def fetch_product_stock(self, product_id):
        import copy
        currency_id = request.args.get('c', None)
        product = Product.get_or_none(Product.id == product_id)
        if not product: return jsonify_with_error(200001, '产品不存在')

        main_currency = Currency.get_main_currency()
        if not main_currency: return jsonify_with_error(9000001, '未设置主币种')

        if currency_id:
            currency = Currency.get_or_none(Currency.id == currency_id)
            if not currency: return jsonify_with_error(300001, '币种不存在')
        else:
            currency = main_currency

        offer_list = Offer.get_list(product)
        offer_list = sorted(offer_list, key=lambda s: s.price)

        recommend_stock = None
        for stock in offer_list:
            # stock.price = round(stock.price * currency.rate, 2)

            if stock.is_recommend():
                recommend_stock = copy.deepcopy(stock)

        if offer_list and not recommend_stock:
            recommend_stock = copy.deepcopy(offer_list[0])
        additional = []
        if recommend_stock:
            from ..models.service import Service
            from decimal import Decimal

            for s in ['TRS', ]:
                service = Service.get_or_none(Service.id == s)
                if not service: continue
                service_fee = Decimal.from_float(0.00)
                if service:
                    if service.mode == 'fixed':
                        service_fee = service.fee
                    elif service.mode == 'rate':
                        service_fee = recommend_stock.price * service.fee
                additional.append({
                    'id': s,
                    'name': service.screen_name,
                    'amount': service_fee
                })

                # recommend_stock.price = round(recommend_stock.price + service_fee, 2)

        return ProductOfferResp(
            context={'currency': currency}).jsonify({'currency': currency,
                                                     'stock': offer_list,
                                                     'recommend': {
                                                         'stock': recommend_stock,
                                                         'additional': additional
                                                     }})
